// tools/LRParser.java
package tools;

import java.util.*;



public class LRParser {
    private final List<LexicalAnalyzer.Token> tokens;
    private final Grammar grammar;
    private final Map<Integer, Map<String, String>> actionTable;
    private final Map<Integer, Map<String, Integer>> gotoTable;

    private final Stack<Integer> stateStack = new Stack<>();
    private final Stack<Node> nodeStack = new Stack<>();

    public LRParser(List<LexicalAnalyzer.Token> tokens) {
        this.tokens = tokens;
        this.grammar = new Grammar();
        LRParserGenerator generator = new LRParserGenerator(grammar);
        //generator.generateTables();
        this.actionTable = generator.getActionTable();
        this.gotoTable = generator.getGotoTable();

        stateStack.push(0); // 初始状态
    }

    public Node parse() throws Exception {
        int tokenIndex = 0;

        while (true) {
            LexicalAnalyzer.Token currentToken;
            String symbol;

            if (tokenIndex < tokens.size()) {
                currentToken = tokens.get(tokenIndex);
                symbol = currentToken.type.name();
            } else {

                currentToken = new LexicalAnalyzer.Token(LexicalAnalyzer.TokenType.UNKNOWN, "",666);
                symbol = "$";
            }

            Integer currentState = stateStack.peek();
            Map<String, String> currentActions = actionTable.get(currentState);
            if (currentActions == null) {
                throw new Exception("无效状态: " + currentState);
            }

            String action = currentActions.get(symbol);
            if (action == null) {
                throw new Exception("语法错误: 在状态 " + currentState + " 遇到符号 " + symbol + "，位置: " + tokenIndex);
            }


            if (action.startsWith("s")) {
                int nextState = Integer.parseInt(action.substring(1));
                stateStack.push(nextState);
                nodeStack.push(new TokenNode(currentToken));
                tokenIndex++;
            } else if (action.startsWith("r")) {
                int ruleIndex = Integer.parseInt(action.substring(1));
                Grammar.Production production = grammar.productions.get(ruleIndex);
                int rhsSize = production.rhs.size();

                for (int i = 0; i < rhsSize; i++) {
                    stateStack.pop();
                }

                List<Node> children = new ArrayList<>();
                for (int i = 0; i < rhsSize; i++) {
                    children.add(0, nodeStack.pop());
                }

                NonTerminalNode newNode = new NonTerminalNode(production.lhs);
                for (Node child : children) {
                    newNode.addChild(child);
                }

                Map<String, Integer> gotoMap = gotoTable.get(stateStack.peek());
                if (gotoMap == null || !gotoMap.containsKey(production.lhs)) {
                    throw new Exception("转移错误: 当前状态 " + stateStack.peek() +
                            " 无法 GOTO " + production.lhs);
                }
                Integer gotoState = gotoMap.get(production.lhs);
                stateStack.push(gotoState);
                nodeStack.push(newNode);
            } else if (action.equals("acc")) {
                // 接受成功
                break;
            } else {
                throw new Exception("未知动作: " + action);
            }

            //System.out.println("状态: " + stateStack.peek() + ", 符号: " + symbol);
        }


        return nodeStack.pop();  // 返回语法树根节点
    }


    // AST节点基类
    public abstract static class Node {

        public abstract void print(int depth);

        public abstract String show(int depth);
    }

    // 终结符节点
    public static class TokenNode extends Node {
        public final LexicalAnalyzer.Token token;

        public TokenNode(LexicalAnalyzer.Token token) {
            this.token = token;
        }

        @Override
        public void print(int depth) {
            System.out.println(" ".repeat(depth) + token);
        }

        @Override
        public String show(int depth) {
            return " ".repeat(depth) + token.type+": "+token.lexeme()+'\n';
        }



        public String lexeme() {
            return token.lexeme();
        }
    }

    // 非终结符节点
    public static class NonTerminalNode extends Node {
        private final String symbol;

        public List<Node> getChildren() {
            return children;
        }

        public String getSymbol() {
            return symbol;
        }

        private final List<Node> children = new ArrayList<>();

        public NonTerminalNode(String symbol) {
            this.symbol = symbol;
        }

        public void addChild(Node child) {
            children.add(child);
        }


        @Override
        public String show(int depth) {
            StringBuilder sb = new StringBuilder();
            sb.append(" ".repeat(depth)).append(symbol).append("\n");
            for (Node child : children) {
                sb.append(child.show(depth + 2));
            }
            return sb.toString();
        }
        @Override
        public void print(int depth) {
            System.out.println(" ".repeat(depth) + symbol);
            for (Node child : children) {
                child.print(depth + 2);
            }
        }
    }


}
